package com.huilian.iotbox.admin.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.huilian.iotbox.admin.service.*;
import com.huilian.iotbox.data.common.RedisKey;
import com.huilian.iotbox.data.common.ServerResponse;
import com.huilian.iotbox.data.dao.UserCommonDao;
import com.huilian.iotbox.data.dao.UserRoleDao;
import com.huilian.iotbox.data.dto.UserAgencyDto;
import com.huilian.iotbox.data.dto.UserDto;
import com.huilian.iotbox.data.enums.*;
import com.huilian.iotbox.data.exception.SysException;
import com.huilian.iotbox.data.po.*;
import com.huilian.iotbox.data.properties.SmsProperties;
import com.huilian.iotbox.data.service.SystemConfigService;
import com.huilian.iotbox.data.service.UserAttributeCommonService;
import com.huilian.iotbox.data.utils.Util;
import com.huilian.iotbox.data.vo.*;
import com.huilian.security.app.jwt.JwtTokenService;
import com.huilian.security.sms.SmsCodeSender;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author 少凡
 * @date 2020/2/23 10:38
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRoleDao userRoleDao;
    @Resource
    private UserCommonDao userCommonDao;
    @Autowired
    private AgencyService agencyService;
    @Autowired
    private SmsCodeSender smsCodeSender;
    @Autowired
    private SmsProperties smsProperties;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private UserRoleService userRoleService;
    @Autowired
    private JwtTokenService jwtTokenService;
    @Autowired
    private UserAgencyService userAgencyService;
    @Autowired
    private SystemConfigService systemConfigService;
    @Autowired
    private UserAttributeCommonService userAttributeCommonService;
    @Autowired
    private RedisTemplate<String, Serializable> redisCacheTemplate;

    /**
     * 根据登录用户名查找用户
     *
     * @param username
     * @param status
     * @return
     */
    @Override
    public User findUserByLoginUserName(String username, Integer status) {
        return userCommonDao.findUserByLoginUserName(username, status);
    }

    /**
     * 获取登录用户权限
     *
     * @param userId
     * @return
     */
    @Override
    public List<Permission> findUserPermission(Object userId) {
        return userCommonDao.findUserPermission(userId);
    }

    @Override
    public UserInfo getLoginUserInfo(HttpServletRequest request) {
        String userId = jwtTokenService.getUserId(request);
        String key = String.format(RedisKey.ADMIN_USERINFO, userId);
        UserInfo userInfo = (UserInfo) redisCacheTemplate.opsForValue().get(key);
        if (StringUtils.isEmpty(userInfo)) {
            userInfo = userCommonDao.getUserInfo(userId);
            if (!StringUtils.isEmpty(userInfo.getRoles()) && userInfo.getRoles().size() > 0) {
                userInfo.setRoleId(userInfo.getRoles().get(0).getRoleId());
            }

            Agency agency = agencyService.findOneAgencyByUserId(userInfo.getId());
            if (!StringUtils.isEmpty(agency)) {
                // 自定义logo
                userInfo.setCustomLogo(agency.getCustomLogo());
                userInfo.setPcLogoFileName(agency.getPcLogoFileName());
                userInfo.setMobileLogoFileName(agency.getMobileLogoFileName());
            }

            //如果平台、机构、商户以外的角色
            if (userInfo.getRoles().stream().filter(roleVo -> roleVo.getRoleId().equals(RoleEnum.SUB_ACCOUNT.getRoleId())).findFirst().isPresent()) {
                //查询出该角色分配的机构集合
                List<Integer> agencyIdList = userCommonDao.getAgencyIdList(userId);
                userInfo.getAgencyIdList().addAll(agencyIdList);

//                UserStore userStore = new UserStore();
//                userStore.setUserId(Integer.parseInt(userId));
//                userStore.setStatus(true);
//                List<Integer> userStoreList = userStoreService.getUserStore(userStore);
//                userInfo.getStoreIdList().addAll(userStoreList);

                UserDto uDto = new UserDto();
                uDto.setAttributeId(AttributeEnum.SUB_ACCOUNT_ADMIN_STORE.getCode());
                uDto.setUserId(Integer.parseInt(userId));
                final List<UserAttribute> list = userAttributeCommonService.findUserAttributeByUserIdList(uDto);
                if (!org.springframework.util.StringUtils.isEmpty(list) && list.size() > 0) {
                    userInfo.getStoreIdList().addAll(list.stream()
                            .map(UserAttribute::getMerchantStoreId)
                            .collect(Collectors.toList()));
                }
            }
            redisCacheTemplate.opsForValue().set(key, userInfo, 24, TimeUnit.HOURS);
        }

        return userInfo;
    }

    @Override
    public List<UserVo> findStaffListByAgencyId(UserVo userVo) {
        List<UserVo> user = userCommonDao.findStaffListByAgencyId(userVo);
        return user;
    }

    @Override
    public ServerResponse checkUserName(User user) {
        if (StringUtils.isEmpty(user.getUsername())) {
            return ServerResponse.createByErrorMessage("请输入登录账号！");
        }

        Integer count = userCommonDao.checkUserName(user);
        if (count > 0) {
            return ServerResponse.createByErrorMessage("该登录账号已存在！");
        }
        return ServerResponse.createBySuccess();
    }

    @Override
    public ServerResponse checkIdCardNo(String idCardNo, String agencyId, UserInfo userInfo) {
        Integer count = userCommonDao.checkIdCardNo(idCardNo, agencyId, userInfo);
        if (count > 0) {
            return ServerResponse.createByErrorMessage("已存在!");
        } else {
            return ServerResponse.createBySuccess();
        }
    }

    @Override
    public int insert(User user) {
        return userCommonDao.insert(user);
    }

    @Override
    public User findUserById(Integer id) {
        return userCommonDao.findUserById(id);
    }

    @Override
    public int update(User user) {
        return userCommonDao.update(user);
    }

    @Override
    public PageInfo<UserVo> findByNameAndMobile(UserDto userDto) {
        PageHelper.startPage(userDto.getPageNum(), userDto.getPageSize());
        List<UserVo> userVoList = userCommonDao.findByNameAndMobile(userDto);
        userVoList.forEach(userVo -> {
            List<UserAgencyVo> userAgencyVoList = userAgencyService.findByUserId(userVo.getId());
            if (!ObjectUtils.isEmpty(userAgencyVoList)) {
                List<Integer> agencyIdList = new ArrayList<>();
                userAgencyVoList.forEach(userAgencyVo -> {
                    agencyIdList.add(userAgencyVo.getAgencyId());
                });
                userVo.setAgencyIdList(agencyIdList);
            }
        });
        return new PageInfo<>(userVoList);
    }

    @Override
    public void addUserAndAddRole(UserDto userDto) {
        try {
            User user = new User();
            user.setPassword(passwordEncoder.encode(userDto.getPassword()));
            user.setOperatePassword(passwordEncoder.encode(userDto.getPassword()));
            user.setMobile(userDto.getMobile());
            user.setUsername(userDto.getUsername());
            user.setAgencyId(userDto.getUserInfo().getAgencyId());
            user.setName(userDto.getName());
            user.setVersion(0);
            user.setStatus(AccountStatusEnum.NORMAL.getCode());
            user.setParentId(userDto.getUserInfo().getId());
            userCommonDao.insert(user);

            //添加允许查看的机构
            userAgencyService.deleteByUserId(user.getId());
            UserAgencyDto userAgencyDto = new UserAgencyDto();
            userAgencyDto.setUserId(user.getId());

            for (Integer i : userDto.getAgencyIdList()) {
                if (!i.equals(userDto.getUserInfo().getAgencyId())) {
                    userAgencyDto.setAgencyId(i);
                    userAgencyService.add(userAgencyDto);
                }
            }

            UserRole userRole = new UserRole();
            userRole.setRoleId(userDto.getRoleId());
            userRole.setUserId(user.getId());
            userRoleDao.insert(userRole);
        } catch (Exception e) {
            e.printStackTrace();
            throw new SysException("添加失败");
        }
    }

    @Override
    public List<User> getAllUserOfName(UserInfo userInfo, String agencyId) {
        if (RoleEnum.SUB_ACCOUNT.getRoleId().equals(userInfo.getRoleId()) && userInfo.getStoreIdList().size() == 0) {
            return new ArrayList<>();
        }
        return userCommonDao.getAllUserOfName(userInfo, agencyId);
    }

    @Override
    public PageInfo findUserList(UserDto userDto) {
        PageHelper.startPage(userDto.getPageNum(), userDto.getPageSize());
        List<UserVo> userList = userCommonDao.findUserList(userDto);
        for (UserVo userVo : userList) {
            List<Integer> list = userRoleService.findListByUserId(userVo.getId());
            userVo.setUserRoleIdList(list);
        }
        PageInfo pagResult = new PageInfo(userList);
        return pagResult;
    }

    @Override
    public ServerResponse registerSmsCode(String mobile) {
        if (StringUtils.isEmpty(mobile)) {
            return ServerResponse.createByErrorMessage("请输入手机号");
        }

        String key = RedisKey.REGISTER_SMSCODE + mobile;
        String s = (String) redisCacheTemplate.opsForValue().get(key + "EXPR");
        if (!ObjectUtils.isEmpty(s)) {
            return ServerResponse.createByErrorMessage("验证码发送频繁!稍后重试");
        }
        redisCacheTemplate.delete(key);
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            sb.append(random.nextInt(10));
        }
        log.info("验证码是: {}", sb);
        log.info("sms-key是: {}", smsProperties.getKey());
        com.huilian.security.sms.common.ServerResponse serverResponse = smsCodeSender.send(mobile, sb.toString(), smsProperties.getKey());

        if (serverResponse.getIsSuccess()) {
            redisCacheTemplate.opsForValue().set(key, sb.toString(), 30, TimeUnit.MINUTES);
            redisCacheTemplate.opsForValue().set(key + "EXPR", "111", 1, TimeUnit.MINUTES);
            return ServerResponse.createBySuccess("已向" + Util.repPhone(mobile) + "手机号成功发送验证码");
        }

        return ServerResponse.createByErrorMessage(serverResponse.getMsg());

    }

    @Override
    public ServerResponse register(UserDto userDto) {
        //判断验证码
        String key = RedisKey.REGISTER_SMSCODE + userDto.getMobile();
        String s = (String) redisCacheTemplate.opsForValue().get(key);
        if (org.apache.commons.lang.StringUtils.isEmpty(s)) {
            return ServerResponse.createByErrorMessage("验证码不存在");
        } else {
            if (!s.equals(userDto.getSmsCode())) {
                return ServerResponse.createByErrorMessage("验证码错误");
            }
        }
        redisCacheTemplate.delete(key);
        SystemConfig systemConfig = systemConfigService.findOneSystemConfigById(1);
        User user = new User();
        user.setPassword(passwordEncoder.encode(userDto.getPassword()));
        user.setOperatePassword(passwordEncoder.encode(userDto.getPassword()));
        user.setMobile(userDto.getMobile());
        user.setUsername(userDto.getMobile());
        user.setAgencyId(userDto.getAgencyId());
        user.setName(userDto.getName());
        user.setVersion(0);
        user.setStatus(AccountStatusEnum.NORMAL.getCode());
        user.setAgencyId(userDto.getUserInfo().getAgencyId());
        user.setBalance(new BigDecimal(0));
        user.setCommissionBalance(new BigDecimal(0));
        user.setReceiptType(MchTypeEnum.OWN.getCode());
        user.setWelfareReturnCoinSum(systemConfig.getDistributeWelfareToMemberByMaxCoin());
        userCommonDao.insert(user);
        UserRole userRole = new UserRole();
        userRole.setRoleId(RoleEnum.MERCHANT.getRoleId());
        userRole.setUserId(user.getId());
        userRoleService.add(userRole);

        return ServerResponse.createBySuccess();
    }

    @Override
    public ServerResponse updatePwd(UserDto userDto) {
        User user = userCommonDao.findUserByLoginUserName(userDto.getUserInfo().getUsername(), UserStatusEnum.WRITE_OFF.getCode());
//        String pwd =  aesDecryptByBytes.aesDecrypt(password);
//        String newPwd = aesDecryptByBytes.aesDecrypt(newPassword);
        boolean isMatches = passwordEncoder.matches(userDto.getPassword(), user.getPassword());
        if (isMatches) {
            User userPwd = new User();
            userPwd.setPassword(passwordEncoder.encode(userDto.getNewPassword()));
            userPwd.setId(userDto.getUserInfo().getId());
            Integer count = userCommonDao.updatePwd(userPwd);
            if (count > 0) {
                return ServerResponse.createBySuccess();
            } else {
                return ServerResponse.createByErrorMessage("密码修改失败");
            }
        } else {
            return ServerResponse.createByErrorMessage("原密码不正确，请重新输入");
        }
    }

    @Override
    public ServerResponse updateUser(UserDto userDto) {
        Integer count = userCommonDao.update(userDto);
        if (count > 0) {
            if (userDto.getReceiptType() != null) {
                String key = String.format(RedisKey.RECEIPT_TYPE, userDto.getId());
                redisCacheTemplate.delete(key);
            }
            if (userDto.getDockingStatus() != null || userDto.getCardStatus() != null || userDto.getPayeeUserId() != null) {
                String key = String.format(RedisKey.ADMIN_USERINFO, userDto.getId());
                redisCacheTemplate.delete(key);
            }
            return ServerResponse.createBySuccess();
        } else {
            return ServerResponse.createByErrorMessage("操作失败");
        }
    }

    @Override
    public Integer findNewOperatorsCount(Integer agencyId, String startTime, String endTime) {
        return userCommonDao.findNewOperatorsCount(agencyId, startTime, endTime);
    }

    @Override
    public Integer findSetUserNoTrade(Integer agencyId, Set<Integer> set) {
        return userCommonDao.findSetUserNoTrade(agencyId, set);
    }

    @Override
    public UserVo findOperatePasswordByOutTradeNoByUserId(String outTradeNo, Integer userId) {
        return userCommonDao.findOperatePasswordByOutTradeNoByUserId(outTradeNo, userId);
    }

    @Override
    public UserVo getUserId(Integer userId) {
        return userCommonDao.getUserId(userId);
    }

    @Override
    public List<User> findAllUserByParentId(Integer userId) {
        return userCommonDao.findAllUserByParentId(userId);
    }

    @Override
    public ServerResponse updateWelfareReturnCoinSum(UserDto userDto) {
        if (!userDto.getUserInfo().getRoleId().equals(RoleEnum.SUPER_ADMINISTRATOR.getRoleId())) {
            return ServerResponse.createByErrorMessage("你没有权限修改！");
        }
        try {
            int i = userCommonDao.updateWelfareReturnCoinSum(userDto);
            if (i <= 0) {
                throw new Exception("数据库修改失败！");
            }
            List<User> userList = userCommonDao.findAllUserByParentId(userDto.getId());
            for (User u : userList) {
                UserDto userDto1 = new UserDto();
                userDto1.setId(u.getId());
                userDto1.setVersion(u.getVersion());
                userDto1.setWelfareReturnCoinSum(userDto.getWelfareReturnCoinSum());
                int flag = userCommonDao.updateWelfareReturnCoinSum(userDto1);
                if (flag <= 0) {
                    throw new Exception("数据库修改失败！");
                }
            }
            String key = String.format(RedisKey.ADMIN_USERINFO, userDto.getId());
            redisCacheTemplate.delete(key);
        } catch (Exception e) {
            e.printStackTrace();
            return ServerResponse.createByErrorMessage("修改失败！" + e.getMessage());
        }
        return ServerResponse.createBySuccess();
    }

    @Override
    public ServerResponse updateLoginUser(User user) {
        UserRole userRole = new UserRole();

        if (user.getRoles() != null) {

            for (RoleVo roleVo : user.getRoles()) {

                userRole.setUserId(user.getId());
                userRole.setRoleId(roleVo.getValue());

                Integer count = userRoleService.findByUserIdAndRoleId(userRole);

                if (roleVo.getChecked() && count == 0) {
                    userRoleService.add(userRole);
                } else if (!roleVo.getChecked() && count != 0) {
                    userRoleService.delete(userRole);
                }
            }
        }

        Integer result = userCommonDao.update(user);
        if (result == 1) {
            String key = String.format(RedisKey.ADMIN_USERINFO, user.getId());
            redisCacheTemplate.delete(key);
            return ServerResponse.createBySuccess();
        } else {
            return ServerResponse.createByError("用户更新失败!");
        }
    }

    @Override
    public ServerResponse updateInfo(UserDto userDto) {
        User user = userCommonDao.findUserById(userDto.getId());
        if (ObjectUtils.isEmpty(user)) {
            return ServerResponse.createByErrorMessage("未找到对应的账号！");
        }
        if (!userDto.getUserInfo().getRoleId().equals(RoleEnum.SUPER_ADMINISTRATOR.getRoleId()) && !user.getParentId().equals(userDto.getUserInfo().getId())) {
            return ServerResponse.createByErrorMessage("你没有权限修改此账号！");
        }

        //添加允许查看的机构
        userAgencyService.deleteByUserId(user.getId());
        UserAgencyDto userAgencyDto = new UserAgencyDto();
        userAgencyDto.setUserId(user.getId());
        for (Integer i : userDto.getAgencyIdList()) {
            if (!i.equals(userDto.getUserInfo().getAgencyId())) {
                userAgencyDto.setAgencyId(i);
                userAgencyService.add(userAgencyDto);
            }
        }

        userCommonDao.updateInfo(user);

        UserRole userRole = userRoleService.findByUserId(userDto.getId());
        if (!userRole.getRoleId().equals(userDto.getRoleId())) {
            userRole.setRoleId(userDto.getRoleId());
            userRoleService.update(userRole);
        }
        redisCacheTemplate.delete(String.format(RedisKey.ADMIN_USERINFO, user.getId()));
        return ServerResponse.createBySuccess();
    }

    @Override
    public ServerResponse resetPwdById(UserDto userDto) {
        User user = userCommonDao.findUserById(userDto.getId());
        if (ObjectUtils.isEmpty(user)) {
            return ServerResponse.createByErrorMessage("未找到对应的账号！");
        }
        if (!userDto.getUserInfo().getRoleId().equals(RoleEnum.SUPER_ADMINISTRATOR.getRoleId())) {
            if (!user.getAgencyId().equals(userDto.getUserInfo().getAgencyId())) {
                return ServerResponse.createByErrorMessage("你没有权限修改此用户！");
            }
        }
        if (StringUtils.isEmpty(user.getMobile())) {
            user.setPassword(passwordEncoder.encode("123456"));
        } else {
            user.setPassword(passwordEncoder.encode(user.getMobile()));
        }
        int i = userCommonDao.updatePwd(user);
        if (i > 0) {

            return ServerResponse.createBySuccess();
        } else {
            return ServerResponse.createByErrorMessage("更新失败！请联系管理员！");
        }
    }

    @Override
    public ServerResponse getCode(UserDto userDto) {
        User user = userCommonDao.findByMobile(userDto);
        if (ObjectUtils.isEmpty(user)) {
            return ServerResponse.createByErrorMessage("未找到对应的账号！");
        }
        String key = RedisKey.FORGET_PASSWORD + userDto.getMobile();
        String s = (String) redisCacheTemplate.opsForValue().get(key + "FP");
        if (!ObjectUtils.isEmpty(s)) {
            return ServerResponse.createByErrorMessage("验证码发送频繁!稍后重试");
        }
        redisCacheTemplate.delete(key);
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            sb.append(random.nextInt(10));
        }
        log.info("验证码是: {}", sb);
        log.info("sms-key是: {}", smsProperties.getKey());
        com.huilian.security.sms.common.ServerResponse serverResponse = smsCodeSender.send(userDto.getMobile(), sb.toString(), smsProperties.getKey());

        if (serverResponse.getIsSuccess()) {
            redisCacheTemplate.opsForValue().set(key, sb.toString(), 30, TimeUnit.MINUTES);
            redisCacheTemplate.opsForValue().set(key + "FP", "111", 1, TimeUnit.MINUTES);
            return ServerResponse.createBySuccess("已向" + Util.repPhone(userDto.getMobile()) + "手机号成功发送验证码");
        }
        return ServerResponse.createByErrorMessage(serverResponse.getMsg());
    }

    @Override
    public ServerResponse forgetPassword(UserDto userDto) {
        User user = userCommonDao.findByMobile(userDto);
        if (ObjectUtils.isEmpty(user)) {
            return ServerResponse.createByErrorMessage("未找到对应的账号！");
        }
        String key = RedisKey.FORGET_PASSWORD + userDto.getMobile();
        String s = (String) redisCacheTemplate.opsForValue().get(key);
        if (ObjectUtils.isEmpty(s)) {
            return ServerResponse.createByErrorMessage("验证码不正确！");
        }
        if (!s.equals(userDto.getVerification())) {
            return ServerResponse.createByErrorMessage("验证码不正确！");
        }
        redisCacheTemplate.delete(key);
        user.setPassword(passwordEncoder.encode(userDto.getNewPassword()));
        user.setOperatePassword(passwordEncoder.encode(userDto.getNewPassword()));
        userCommonDao.updatePwd(user);
        return ServerResponse.createBySuccess();
    }

    @Override
    public ServerResponse changeSignStatus(UserDto userDto) {
        userDto.setSignStatus(true);
        userCommonDao.changeSignStatus(userDto);
        String key = String.format(RedisKey.ADMIN_USERINFO, userDto.getId());
        redisCacheTemplate.delete(key);
        return ServerResponse.createBySuccess();
    }

    @Override
    public ServerResponse checkMobile(String mobile) {
        Integer count = userCommonDao.checkMobile(mobile, UserStatusEnum.WRITE_OFF.getCode());
        if (count > 0) {
            return ServerResponse.createByErrorMessage("已存在!");
        } else {
            return ServerResponse.createBySuccess();
        }
    }

    @Override
    public ServerResponse resetOperatePwdById(UserDto userDto) {
        User user = userCommonDao.findUserById(userDto.getId());
        if (ObjectUtils.isEmpty(user)) {
            return ServerResponse.createByErrorMessage("未找到对应的账号！");
        }
        if (!userDto.getUserInfo().getRoleId().equals(RoleEnum.SUPER_ADMINISTRATOR.getRoleId())) {
            if (!user.getAgencyId().equals(userDto.getUserInfo().getAgencyId())) {
                return ServerResponse.createByErrorMessage("你没有权限修改此用户！");
            }
        }
        if (StringUtils.isEmpty(user.getMobile())) {
            user.setOperatePassword(passwordEncoder.encode("123456"));
        } else {
            user.setOperatePassword(passwordEncoder.encode(user.getMobile()));
        }
        int i = userCommonDao.updatePwd(user);
        if (i > 0) {
            return ServerResponse.createBySuccess(StringUtils.isEmpty(user.getMobile()) ? "123456" : "当前账号的手机号");
        } else {
            return ServerResponse.createByErrorMessage("更新失败！请联系管理员！");
        }
    }

    @Override
    public List<User> getAllUserSubAccountOfName(UserInfo userInfo,String userIdType) {
        return userCommonDao.getAllUserSubAccountOfName(userInfo,userIdType);
    }

}
